package com.ruicar.afs.cloud.batch.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruicar.afs.cloud.batch.entity.AfsBatchInfo;
import com.ruicar.afs.cloud.batch.entity.AfsBatchJobStepInfo;
import com.ruicar.afs.cloud.batch.entity.AfsBatchLogStep;
import com.ruicar.afs.cloud.batch.enums.BatchType;
import com.ruicar.afs.cloud.batch.enums.MessageType;
import com.ruicar.afs.cloud.batch.enums.RunStatus;
import com.ruicar.afs.cloud.batch.frame.logger.WsMonitorHelper;
import com.ruicar.afs.cloud.batch.mapper.AfsBatchLogStepMapper;
import com.ruicar.afs.cloud.batch.service.AfsBatchInfoService;
import com.ruicar.afs.cloud.batch.service.AfsBatchLogStepService;
import com.ruicar.afs.cloud.common.core.constant.CommonConstants;
import com.ruicar.afs.cloud.common.data.datasource.annotation.DS;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.text.MessageFormat;
import java.util.List;

@Service
@Slf4j
@AllArgsConstructor
public class AfsBatchLogStepServiceImpl extends ServiceImpl<AfsBatchLogStepMapper, AfsBatchLogStep> implements AfsBatchLogStepService {
    private final AfsBatchInfoService afsBatchInfoService;
    @Override
    @DS(CommonConstants._BASE_DS_NAME)
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW)
    public boolean hasFinish(AfsBatchJobStepInfo afsBatchJobStepInfo, String bhDate ) {
        AfsBatchLogStep afsBatchLogStep = this.getOne(Wrappers.<AfsBatchLogStep>lambdaQuery().eq(AfsBatchLogStep::getStepNo, afsBatchJobStepInfo.getStepNo()).eq(AfsBatchLogStep::getBatchNo, afsBatchJobStepInfo.getBatchNo()).eq(AfsBatchLogStep::getSystemName, afsBatchJobStepInfo.getSystemName()).eq(AfsBatchLogStep::getBatchDate,bhDate));
        if(afsBatchLogStep !=null&& afsBatchLogStep.getStepStatus()==RunStatus.FINISHED) {
            return true;
        }
        return false;
    }

    @Override
    @DS(CommonConstants._BASE_DS_NAME)
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW)
    public RunStatus doLog(AfsBatchJobStepInfo afsBatchJobStepInfo, String bhDate) {
        AfsBatchLogStep afsBatchLogStep = this.getOne(Wrappers.<AfsBatchLogStep>lambdaQuery().eq(AfsBatchLogStep::getStepNo, afsBatchJobStepInfo.getStepNo()).eq(AfsBatchLogStep::getBatchNo, afsBatchJobStepInfo.getBatchNo()).eq(AfsBatchLogStep::getSystemName, afsBatchJobStepInfo.getSystemName()).eq(AfsBatchLogStep::getBatchDate,bhDate));
        if(afsBatchLogStep ==null) {
            afsBatchLogStep = new AfsBatchLogStep();
            afsBatchLogStep.setBatchDate(bhDate);
            afsBatchLogStep.setStepNo(afsBatchJobStepInfo.getStepNo());
            afsBatchLogStep.setStepStatus(RunStatus.RUNNING);
            afsBatchLogStep.setBatchNo(afsBatchJobStepInfo.getBatchNo());
            afsBatchLogStep.setSystemName(afsBatchJobStepInfo.getSystemName());
            afsBatchLogStep.setStartTime(DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_PATTERN));
            this.save(afsBatchLogStep);
        }else{
            if(afsBatchLogStep.getStepStatus()==RunStatus.ERROR){
                log.info("步骤[{}]-[{}]-[{}]-[{}]处于异常状态，恢复至正常状态继续进行", afsBatchJobStepInfo.getSystemName(), afsBatchJobStepInfo.getBatchNo(), afsBatchJobStepInfo.getStepNo(), afsBatchJobStepInfo.getStepName());
                WsMonitorHelper.sendMessage(MessageType.INFO, MessageFormat.format("步骤[{0}]-[{1}]-[{2}]-[{3}]处于异常状态，恢复至正常状态继续进行", afsBatchJobStepInfo.getSystemName(), afsBatchJobStepInfo.getBatchNo(), afsBatchJobStepInfo.getStepNo(), afsBatchJobStepInfo.getStepName()));
                afsBatchLogStep.setStepStatus(RunStatus.RUNNING);
            }
            this.updateById(afsBatchLogStep);
        }
        return afsBatchLogStep.getStepStatus();
    }

    @Override
    @DS(CommonConstants._BASE_DS_NAME)
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW)
    public void saveError(AfsBatchJobStepInfo afsBatchJobStepInfo, String errorStack, String bhDate) {
        AfsBatchLogStep afsBatchLogStep = this.getOne(Wrappers.<AfsBatchLogStep>lambdaQuery().eq(AfsBatchLogStep::getStepNo, afsBatchJobStepInfo.getStepNo()).eq(AfsBatchLogStep::getBatchNo, afsBatchJobStepInfo.getBatchNo()).eq(AfsBatchLogStep::getSystemName, afsBatchJobStepInfo.getSystemName()).eq(AfsBatchLogStep::getBatchDate,bhDate));
        if(afsBatchLogStep ==null) {
            afsBatchLogStep = new AfsBatchLogStep();
            afsBatchLogStep.setBatchDate(bhDate);
            afsBatchLogStep.setStepNo(afsBatchJobStepInfo.getStepNo());
            afsBatchLogStep.setStepStatus(RunStatus.ERROR);
            afsBatchLogStep.setBatchNo(afsBatchJobStepInfo.getBatchNo());
            afsBatchLogStep.setSystemName(afsBatchJobStepInfo.getSystemName());
            afsBatchLogStep.setStepExceptionStack(errorStack);
            afsBatchLogStep.setStartTime(DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_PATTERN));
            this.save(afsBatchLogStep);
        }else{
            afsBatchLogStep.setStepStatus(RunStatus.ERROR);
            afsBatchLogStep.setStepExceptionStack(errorStack);
            this.updateById(afsBatchLogStep);
        }
        afsBatchInfoService.update(Wrappers.<AfsBatchInfo>lambdaUpdate().eq(AfsBatchInfo::getSystemName,afsBatchJobStepInfo.getSystemName()).eq(AfsBatchInfo::getBatchType, BatchType.ALL).set(AfsBatchInfo::getBatchType,afsBatchJobStepInfo.getBatchType()));
    }

    @Override
    @DS(CommonConstants._BASE_DS_NAME)
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW)
    public void finished(AfsBatchJobStepInfo afsBatchJobStepInfo, String bhDate) {
        AfsBatchLogStep afsBatchLogStep = this.getOne(Wrappers.<AfsBatchLogStep>lambdaQuery().eq(AfsBatchLogStep::getStepNo, afsBatchJobStepInfo.getStepNo()).eq(AfsBatchLogStep::getBatchNo, afsBatchJobStepInfo.getBatchNo()).eq(AfsBatchLogStep::getSystemName, afsBatchJobStepInfo.getSystemName()).eq(AfsBatchLogStep::getBatchDate,bhDate));
        if(afsBatchLogStep ==null) {
            afsBatchLogStep = new AfsBatchLogStep();
            afsBatchLogStep.setBatchDate(bhDate);
            afsBatchLogStep.setStepNo(afsBatchJobStepInfo.getStepNo());
            afsBatchLogStep.setStepStatus(RunStatus.FINISHED);
            afsBatchLogStep.setBatchNo(afsBatchJobStepInfo.getBatchNo());
            afsBatchLogStep.setSystemName(afsBatchJobStepInfo.getSystemName());
            afsBatchLogStep.setStepExceptionStack(null);
            afsBatchLogStep.setStartTime(DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_PATTERN));
            afsBatchLogStep.setFinishTime(DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_PATTERN));
            this.save(afsBatchLogStep);
        }else{
            afsBatchLogStep.setStepStatus(RunStatus.FINISHED);
            afsBatchLogStep.setFinishTime(DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_PATTERN));
            afsBatchLogStep.setStepExceptionStack("");
            this.updateById(afsBatchLogStep);
        }
    }

    @Override
    @DS(CommonConstants._BASE_DS_NAME)
    public AfsBatchLogStep queryError(String bhDate) {
        List<AfsBatchLogStep> logStepList = this.list(Wrappers.<AfsBatchLogStep>lambdaQuery().eq(AfsBatchLogStep::getBatchDate,bhDate).eq(AfsBatchLogStep::getStepStatus,RunStatus.ERROR));
        if(CollectionUtil.isEmpty(logStepList)){
            return null;
        }else{
            return logStepList.get(0);
        }
    }
}
